/**
 * \defgroup Unit Unit
 * \brief Unit classes.
 * 
 * A group for everything related to units and their AI.
 * 
 * \file Unit.h
 * \brief Header for Unit class.
 * \ingroup Unit
 */

#ifndef UNIT_H
#define UNIT_H

#include<QObject>
#include<QString>

class Field;
class Map;

/**
 * \enum UnitAge
 * \brief All current ages of the game.
 * \ingroup Unit
 */

enum UnitAge{
	AGE_BRZ,
	AGE_IRN,
	AGE_EMA,
	AGE_HMA,
	AGE_LMA,
	AGE_CA,
	AGE_IA
};

/**
 * \enum UnitType
 * \brief All unit types of the game.
 * 
 * Due to age/type defining the unit, a rogue, for example, could not be simulated this way.
 * \ingroup Unit
 */

enum UnitType{
	TYPE_LM,
	TYPE_FM,
	TYPE_HM,
	TYPE_SR,
	TYPE_LR
};

/**
 * \enum Team
 * \brief To distinguish between the two teams.
 * \ingroup Unit
 */

enum Team{
	TEAM_A,
	TEAM_B
};

class Unit;

/**
 * \struct UnitAndPriority
 * \brief A simple struct containing a \a Unit and its attack priority.
 * \ingroup Unit
 */
struct UnitAndPriority{
	Unit *unit;///<The \a Unit in question.
	int priority;///<The priority for attacking this \a Unit.
	
	UnitAndPriority( Unit *unit, int priority ){ this->unit = unit; this->priority = priority; }///<Constructor. \param unit \a Unit \param priority Its priority.
	UnitAndPriority() {}///<Constructor.
};

/**
 * \struct FieldPriority
 * \brief A struct used for determining the priority of a \a Field
 * 
 * Contains several parameters to determine the \a Field 's priority.
 * \ingroup Unit
 */

struct FieldPriority{
	Field *field;	///< The field in question.
	int attack;	///<Value of the possible attack same turn
	int terrain;	///<Value for the terrain, should be 0-1-2
	int defense;	///<Inverse of: How many enemy units can hit me in this position (after movement)?
	int proximity;	///<Value for distance to (not sure) mid of army / highest priority unit \todo Should probably be improved...
	int expectAttackNextTurn; ///<Value of the expected attack next turn.
	bool retaliation;///<If can suffer retaliation damage. (from highest priority unit attackable from this \a Field)
	int coherence;	///<Similar to proximity, but signifies the distance to the middle of the own team.
	QString reason;	///<To add to the log IF AND ONLY IF this \a Field is moved to.
};

/**
 * \fn int compareUnitPriority(const void *unitPriority1, const void *unitPriority2);
 * \brief Unit comparison function.
 * \param unitPriority1 Pointer to first \a UnitAndPriority struct.
 * \param unitPriority2 Pointer to second \a UnitAndPriority struct.
 * \ingroup Unit
 */
int compareUnitPriority(const void *unitPriority1, const void *unitPriority2);

/**
 * \class Unit
 * \brief The class to represent a unit. It is subclassed to represent the different unit types.
 * 
 * The class to represent a unit. Almost all of the AI logic is found in this class.
 * \ingroup Unit
 */

class Unit: public QObject{
Q_OBJECT
public:
	virtual ~Unit(); ///< Destructor.
	
	QString name()const{ return m_name; }	///<Unit's (full) name
	QString tag()const{ return m_tag; }	///<Unit type abbreviation (such as LM for light melee)
	
	void doAIMove();	///<Decide the move for this \a Unit. All AI logic originates here.
	void attackIfCan(QList<UnitAndPriority> unitPriority);	///<Causes this \a Unit to attack highest priority opponent in range. \param unitPriority decides the priority.
	bool canAttack(Unit *other);	///<Return if can attack \param other
	void attack(Unit *other);	///<Attacks \param other
	bool canRetaliate(Unit *other);	///<Return if can retaliate to other. \param other The \a Unit to retaliate to.
	bool canRetaliate(bool immediately = false)const;	///<Return if can retaliate in general. \param immediately causes it to be interpreted as if being capable to retaliate immediately
	void retaliate(Unit *other);	///<Causes unit to retaliate to \param other
	void damage(int dmg);		///<Does \param dmg damage to \a Unit.
	void die();			///<Kills \a Unit and removes it from \a Map.
	
	QList<UnitAndPriority> getAttackPriority();	///<Returns (sorted) list of \a UnitAndPriority for all enemies.
	virtual double getAttackPriority(const Unit *unit)const=0;	///<Returns priority of one specific unit. \param unit The \a Unit to calculate the priority of.
	
	//BEGIN: New system :P
	int getAttackPriorityForField(Field *field, const QList<UnitAndPriority> &unitPriority)const;///<Returns the "attack" priority for this field, determined by which enemies (of which priority) are in range from here.
	virtual int getFieldPriorityForField(Field *field)const=0;	///<Returns "field" priority for this field, determined by the terrain type.
	int getDefensePriorityForField(Field *field, const QList<UnitAndPriority> &unitPriority)const;///<Returns the "defense" priority for this field, determined by how many units will be able to attack this one in their next turn. A priority of 8 means noone can attack.
	int getProximityPriorityForField(Field *field, const QList<UnitAndPriority> &unitPriority)const;///<Returns the "proximity" priority for this field. Proximity is higher if it is closer to the enemy, smaller if further away.
	bool getRetaliateForField(Field *field, const QList<UnitAndPriority> &unitPriority)const;///<Returns if we would suffer retaliation damage if attacking from this \a Field.
	int getExpectAttackNextTurnForField(Field *field, const QList<UnitAndPriority> &unitPriority)const;///<Returns if we would be able to attack next turn, if moving here in the current turn.
	int getCoherenceForField(Field *field)const;///<Returns the "coherence" priority for this field, which is higher the closer it stays to its own team.
	void selectField(FieldPriority *priorities, int num, int (*sort_func)(const void*, const void*))const;///<Replacement function for qsort. This is not a sorting function, it just ensures the most interesting \a Field to be placed at priorities[0]. \param priorities The \a FieldPriority list to be sorted. \param num The amount of entries in the list. \param sort_func The sorting function to be used.
	//END: New System :P
	
	int health()const{ return m_health; }///<Current health of the \a Unit
	int attack(bool includeTerrainBonus = false)const{ return includeTerrainBonus? m_attack+attackTerrainBonus() : m_attack; }///<Attack value of \a Unit, \param includeTerrainBonus specifies if attack bonus from terrain should be included.
	int defense(bool includeTerrainBonus = false)const{ return includeTerrainBonus ? m_defense + defenseTerrainBonus() : m_defense; }///<Defense value of \a Unit, \param includeTerrainBonus specifies if defense bonus from terrain should be included.
	int range()const{ return m_range; }///<Range value of the \a Unit.
	int speed()const{ return m_speed; }///<Speed value of the \a Unit.
	Team team()const{ return m_team; }///<Team the \a Unit is on.
	
	int damageTo(Unit *other)const;///<Calculates damage this \a Unit can do to the other. \param other The \a Unit to attack.
	virtual int defenseBonusAgainst(UnitType type)const=0;///<Virtual function that returns the defense bonus against another \a UnitType
	virtual int attackBonusAgainst(UnitType type)const=0;///<Virtual function that returns the attack bonus against another \a UnitType
	virtual int attackTerrainBonus()const=0;///<Virtual function that returns the attack bonus from the terrain.
	virtual int defenseTerrainBonus()const=0;///<Virtual function that returns the defense bonus from the terrain.
	
	Map *map()const{ return m_map; }///<Returns the \a Map this \a Unit is on.
	Field *field()const{ return m_field; }///<Returns the one particular \a Field this \a Unit is on.
	void setField(Field *field);///<Assigns \a Unit to \a Field. Will modify \a Field too.
	
	virtual UnitType type()const=0;///<Returns \a UnitType of \a Unit.
	
	QString posToString()const;///<Returns \a Unit 's position as a string.
signals:
	void tookDamage();///<Emitted when damage is taken. Will be caught by \a Map and used by \a MapDisplay.
protected:
	Unit(Map *map, Team team, QString fullName, QString tag, UnitAge age);///<Constructor. \param map the \a Map for this game. \param team The \a Team this \a Unit is on. \param fullName Unit's name. \param tag Tag for the unit's type. \param age The \a UnitAge this Unit's from.
	
	int m_health;///<Current health.
	int m_attack;///<\a Unit 's attack value.
	int m_defense;///<\a Unit 's defense value.
	int m_range;///<\a Unit 's range value.
	int m_speed;///<\a Unit 's speed value.
	Team m_team;///<\a Unit 's \a Team.
	UnitAge m_age;///<\a Unit 's \a UnitAge.
	
	bool m_hasRetaliated;///<Returns wether or not this \a Unit has retaliated this turn. Always true for units that cannot retaliate.
	
	Map *m_map;///<The \a Map this \a Unit 's on.
	Field *m_field;///<The one specific \a Field this \a Unit occupies.
	QString m_name;///<\a Unit 's name.
	QString m_tag;///<\a Unit 's type tag. (such as LM for Light Melee).
};

#endif
